#include "Distance.h"

Distance::Distance()
{
	Dtype = NORMAL;
}

void Distance::Load(string filename)
{
	ifstream myfile(filename.c_str());
	string line;
	if(myfile == NULL)
	{
		cerr<<"Cannot Open Distance File"<<endl;
		exit(1);
	}
	getline(myfile , line);
	ClearSpaces(line);
	if(line == "NORMAL")
		Dtype = NORMAL;
	else
	{
		cerr<<"Cannot Recognize Distance Type"<<endl;
		exit(1);
	}
	getline(myfile , line);	//Match:
	getline(myfile , line);
	ClearSpaces(line);
	while(line != "Delete:" && !myfile.eof()) // match might be another line after the loop finishes
	{
		Match match;
		int i(0);
		while(line[i] != '|')
		{
			match.a += line[i++];
		}
		i++;
		while(line[i] != '|')
		{
			match.b += line[i++];
		}
		i++;
		match.distance=0;
		while(line[i] != '\0')
		{
			match.distance = match.distance*10 + (line[i++]-'0');
		}
		MatchList.push_front(match);
		getline(myfile , line);
		ClearSpaces(line);
	}
	if(line == "Delete:")//delete - goes untill the end of the file
	{
		while(!myfile.eof())
		{
			getline(myfile , line);
			ClearSpaces(line);
			Delete del;
			int i(0);
			while(line[i] != '|')
			{
				del.a += line[i++];
			}
			i++;
			del.distance=0;
			while(line[i] != '\0')
			{
				del.distance = del.distance*10 + (line[i++]+'0');
			}
			DeleteList.push_front(del);
		}
	}
	else //there is another last match line
	{
		Match match;
		int i(0);
		while(line[i] != '|')
		{
			match.a += line[i++];
		}
		i++;
		while(line[i] != '|')
		{
			match.b += line[i++];
		}
		i++;
		match.distance=0;
		while(line[i] != '\0')
		{
			match.distance = match.distance*10 + (line[i++]+'0');
		}
		MatchList.push_front(match);
	}
}

void Distance::Clear()
{
	MatchList.clear();
	DeleteList.clear();
}

bool Distance::IsEmpty() const
{
	if(DeleteList.empty() && MatchList.empty())
		return true;
}

int Distance::DeleteNode(Tree* t1)
{
	list<Delete>::iterator iter=DeleteList.begin();
	while(iter != DeleteList.end())
	{
		if(iter->a == t1->getData()->getLabel())
			return iter->distance;
		iter++;
	}
	if(Dtype == NORMAL)
		return 1;
}

void Distance::SetDtype(DistanceType type)
{
	Dtype = type;
}

int Distance::DeleteTree(Tree* t1)
{
	int distance(0);
	if(t1->getChildrenCount() == 0)
		return DeleteNode(t1);
	for(int i=0; i<t1->getChildrenCount(); i++)
	{
		distance += DeleteTree(t1->getChild(i));
	}
	distance += DeleteNode(t1);
	return distance;
}

int Distance::MatchNodes(Tree *t1, Tree *t2)
{
	list<Match>::iterator iter=MatchList.begin();
	while(iter != MatchList.end())
	{
		if((iter->a == t1->getData()->getLabel() && iter->b == t2->getData()->getLabel()) ||
		   (iter->b == t1->getData()->getLabel() && iter->a == t2->getData()->getLabel()))
			return iter->distance;
		iter++;
	}
	if(Dtype == NORMAL)
	{
		if(t1->getData()->getLabel() == t2->getData()->getLabel())
			return 0;
		else
			return 1;
	}
}

void Distance::UpdateTreeDeleteCosts(Tree *T)
{
	int DT=0;
	for(int i=0; i< T->getChildrenCount(); i++)
	{
		UpdateTreeDeleteCosts(T->getChild(i));
		DT += T->getChild(i)->getData()->getDT();
	}
	T->getData()->setDT(DT + DeleteNode(T));
}
